home *** CD-ROM | disk | FTP | other *** search
-
- char title [] = "Zoing! 1.0 (c) 1986 Alonzo Gariepy, Public Domain";
-
- /* Simulates elastic collision of multiple balls in rectangular area. */
- /* See the doc file accompanying this source code. */
- /* */
- /* 31 August 1986 Finished and released version 1.0, AMG */
- /* */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <intuition/intuition.h>
- #include <graphics/sprite.h>
-
- #define ONE_POINT_TWO 0 /* I'd rather do this dynamically */
-
- #define MAXBALLS 8
- #define BALLS balls_used /* defined on command line. */
- #define FRACBITS 6 /* 0<x<7 fixed point integers. */
- #define GRAVITY gravity /* defined by user. 2 is good. */
- #define LEVITY levity /* defined by user. 1 is best. */
- #define IS_HIRES 1 /* workbench always high res. */
- #define IS_INTERLACE is_interlace /* variable due to interlace. */
- #define STEPSPERFRAME 2 /* 0<x<? simulation resolution */
- #define SHIFTX (FRACBITS-IS_HIRES)
- #define SHIFTY shift_y /* variable due to interlace. */
- #define MINX 0
- #define MINY 0
- #define MAXX (SIMX (304))
- #define MAXY max_y /* variable due to interlace. */
-
- /* defined in arguments */
- long BALLS, IS_INTERLACE, SHIFTY, MAXY, GRAVITY, LEVITY;
-
-
- #define BALL_SPRITE happyr
- #define CURSOR_SPRITE charlie
- #define HEAD_SPRITE harryr
- #define WEIRD_SPRITE sunnyw
- #define SIZEOF_SPRITE 36 /* total words including posctl and term */
-
- #define CURSORDX 7 /* The offset from pointer to cursor sprite */
- #define CURSORDY 7
- #define D (SIMX (16))
-
- #define CONX(x) ((x) << SHIFTX)
- #define CONY(y) ((y) << SHIFTY)
- #define SCREENX(x) ((x) >> SHIFTX)
- #define SCREENY(y) ((y) >> SHIFTY)
- #define SIMX(x) ((x) << FRACBITS)
- #define SIMY(y) ((y) << FRACBITS)
-
- struct NewWindow windef = {
- 0, 0, 84 + 8*sizeof(title) - 7, 20,
- -1, -1,
- CLOSEWINDOW,
- WINDOWCLOSE | WINDOWDEPTH | WINDOWDRAG | WINDOWSIZING,
- NULL, NULL,
- title,
- NULL, NULL, 84 + 8*sizeof("Zoing!") - 9, 0, 0, 0,
- WBENCHSCREEN
- };
-
- extern UWORD charlie [SIZEOF_SPRITE];
- extern UWORD amused [SIZEOF_SPRITE];
- /* and you thought Castro was a yogurt for Unix programmers */
- extern UWORD happyw [SIZEOF_SPRITE];
- extern UWORD angryr [SIZEOF_SPRITE];
- extern UWORD happyr [SIZEOF_SPRITE];
- extern UWORD sunnyw [SIZEOF_SPRITE];
- extern UWORD harryr [SIZEOF_SPRITE];
-
- long framecount = 0;
- long cursor = 0; /* boolean flag: window and cursor ball active */
- long angry [MAXBALLS];
- long alt_on [MAXBALLS];
-
- struct SimpleSprite spr[MAXBALLS];
- struct Window *win;
- struct ViewPort *vp;
-
- UWORD *sprbuf;
-
- long x [MAXBALLS] = {0, SIMX(300),
- SIMX(128),
- SIMX(114), SIMX(114),
- SIMX(100), SIMX(100), SIMX(100), };
-
- long y [MAXBALLS] = {0, SIMY(10),
- SIMY(92),
- SIMY(84), SIMY(100),
- SIMY(76), SIMY(92), SIMY(108), };
-
- long vx [MAXBALLS] = {0, -180, 0, 0, 0, 0, 0, 0,};
- long vy [MAXBALLS] = {0, 70, 0, 0, 0, 0, 0, 0,};
-
- UWORD *sprites [MAXBALLS] = {charlie, sunnyw, harryr, happyr,
- happyr, happyr, happyr, happyr, };
-
- UWORD *sprites_alt [MAXBALLS] = {amused, sunnyw, harryr, angryr,
- angryr, angryr, angryr, angryr, };
-
- long GfxBase, IntuitionBase;
-
- main (argc, argv)
- long argc;
- char *argv[];
- {
- int i;
-
- openwindow ();
- arguments (argc, argv);
- copysprites ();
- defineballs ();
-
- for (;;)
- {
- trackcursor ();
- doIDCMP ();
- WaitTOF (vp);
- for (i = 0; i < STEPSPERFRAME; ++i)
- {
- collisions ();
- moveballs ();
- }
- showballs ();
- }
- }
-
- arguments (argc, argv)
- long argc;
- char *argv [];
- {
- struct Screen screen;
- char *name = (char *)0, usage [sizeof (title)];
- long i, string = 0;
-
- for (i = 0; i < sizeof (usage) - 1;)
- if (name && (usage [i] = *name))
- ++name, ++i;
- else
- {
- switch (string)
- {
- case 0: name = " Usage: ";
- string = 1;
- continue;
- case 1: name = argv [0];
- string = 2;
- continue;
- case 2: name = " balls(1..10) gravity(0..8) ";
- string = 3;
- continue;
- case 3: break;
- }
- break;
- }
- usage [sizeof(usage) - 1] = (char)0;
-
- BALLS = MAXBALLS;
- GRAVITY = 0;
- LEVITY = 0;
- switch (argc)
- {
- case 4:
- LEVITY = atoi (argv [3]);
- if (LEVITY < 0 || LEVITY > 5)
- seppuku (usage);
- #ifdef VERS12
- if (LEVITY && ONE_POINT_TWO)
- ActivateWindow (win);
- #endif
- case 3:
- GRAVITY = atoi (argv [2]);
- if (GRAVITY < 0 || GRAVITY > 10)
- seppuku (usage);
- case 2:
- BALLS = atoi (argv [1]) + 1;
- if (*argv [1] == '?' || BALLS < 2 || BALLS > MAXBALLS)
- seppuku (usage);
- default:
- break;
- }
-
- #ifdef VERS12
- if (ONE_POINT_TWO)
- {
- if (!GetScreenData (&screen, sizeof(screen), WBENCHSCREEN, NULL))
- seppuku ("Zoing! No workbench.");
- IS_INTERLACE = (screen.Height > 300) ? 1 : 0;
- SHIFTY = FRACBITS - IS_INTERLACE;
- MAXY = CONY(screen.Height) - SIMY(16);
- }
- else
- {
- #endif
- IS_INTERLACE = 0;
- SHIFTY = FRACBITS;
- MAXY = CONY(200) - SIMY(16);
- #ifdef VERS12
- }
- #endif
- }
-
- trackcursor ()
- {
- static long oldx, oldy;
- register long xx, yy;
-
- if (win->Flags & WINDOWACTIVE)
- {
- x [0] = xx = CONX (win->WScreen->MouseX) - SIMX (CURSORDX);
- y [0] = yy = CONY (win->WScreen->MouseY) - SIMX (CURSORDX);
-
- if (cursor)
- {
- vx [0] = (xx - oldx) / STEPSPERFRAME;
- vy [0] = (yy - oldy) / STEPSPERFRAME;
- }
- else
- {
- vx [0] = vy [0] = 0;
- cursor = 1;
- }
- oldx = xx;
- oldy = yy;
- }
- else
- {
- cursor = 0;
- }
- }
-
-
- moveballs () /* move the balls and reflect from walls */
- {
- register int i;
-
- x [0] += vx [0];
- y [0] += vy [0];
-
- for (i = 1; i < BALLS; i++)
- {
- x [i] += vx [i];
- y [i] += vy [i];
-
- for (;;) /* we might require several bounces */
- {
- if (x [i] <= MINX)
- x [i] = MINX + MINX - x [i], vx [i] = -vx [i];
- if (x [i] >= MAXX)
- x [i] = MAXX + MAXX - x [i], vx [i] = -vx [i];
- if (x [i] >= MINX)
- break;
- }
-
- vy [i] += LEVITY;
- for (;;)
- {
- if (y [i] <= MINY)
- y [i] = MINY + MINY - y [i], vy [i] = -vy [i];
- if (y [i] >= MAXY)
- y [i] = MAXY + MAXY - y [i], vy [i] = -vy [i];
- if (y [i] >= MINY)
- break;
- }
- vy [i] += GRAVITY;
- }
- }
-
- showballs ()
- {
- int i;
-
- ++framecount;
-
- for (i = 1; i < BALLS; ++i)
- {
- if (alt_on [i] != angry [i])
- {
- ChangeSprite (vp, spr+i, angry[i] ? sprites_alt[i] : sprites[i]);
- alt_on [i] = angry [i];
- }
- MoveSprite (vp, spr + i, SCREENX (x [i]), SCREENY (y [i]));
- }
-
- /* I used to make the cursor gloat here, but it was too distracting! */
- }
-
- openwindow ()
- {
-
- if (!(IntuitionBase = OpenLibrary ("intuition.library", 0)))
- seppuku ("Zoing! Can't open Intuition.");
-
- if (!(GfxBase = OpenLibrary ("graphics.library", 0)))
- seppuku ("Zoing! Can't open graphics.");
-
- if (!(win = (struct Window *) OpenWindow (&windef)))
- seppuku ("Zoing! Can't open window.");
- vp = (struct ViewPort *) ViewPortAddress (win);
- }
-
- defineballs ()
- {
- long i, j, color, red, green, blue;
-
- for (i = 16; i <= 19; ++i)
- {
- color = GetRGB4 (vp->ColorMap, i);
- red = color >> 8 & 0xF;
- green = color >> 4 & 0xF;
- blue = color & 0xF;
-
- for (j = 4; j <= 12; j += 4)
- SetRGB4 (vp, i + j, red, green, blue);
- }
-
- for (i = 1; i < BALLS; i++)
- {
- if (GetSprite (spr + i, -1) < 0)
- seppuku ("Zoing! Sprite allocation failed. ");
-
- spr [i].height = 16;
- spr [i].x = SCREENX (x [i]);
- spr [i].y = SCREENY (y [i]);
-
- ChangeSprite (vp, spr + i, sprites [i]);
- }
-
- SetPointer (win, sprites [0], 16, 16, -CURSORDX, -CURSORDY);
- SetWindowTitles (win, title, title);
- }
-
- free_resources ()
- {
- register int i;
-
- for (i = 1; i < BALLS; i++)
- if (spr [i].num)
- FreeSprite ((long) spr [i].num);
-
- if (sprbuf)
- FreeMem (sprbuf, 2*2*SIZEOF_SPRITE * BALLS);
- if (win)
- CloseWindow (win);
- if (GfxBase)
- CloseLibrary (GfxBase);
- if (IntuitionBase)
- CloseLibrary (IntuitionBase);
- }
-
- doIDCMP ()
- {
- long msg;
-
- if (msg = GetMsg (win -> UserPort))
- {
- ReplyMsg (msg);
- free_resources ();
- /* printf ("framecount = %ld\n", framecount); */
- /* Sorry, not under Workbench. jjf 06-sep-86 */
- exit (0);
- }
- }
-
- seppuku (str)
- char *str;
- {
- if (win)
- {
- SetWindowTitles (win, str, -1);
- #ifdef VERS12
- if (ONE_POINT_TWO)
- ActivateWindow (win); /* don't die quietly */
- #endif
- WaitPort (win -> UserPort);
- }
- free_resources ();
- exit (100);
- }
-
- copysprites ()
- {
- UWORD *cw; /* current position in buffer of sprite images */
- UWORD *sprite; /* current position in sprite */
- int i, j;
-
- if (!(sprbuf = (UWORD *)
- AllocMem (2 * 2*SIZEOF_SPRITE * BALLS, MEMF_CHIP)))
- seppuku ("Zoing! Can't allocate sprite buffer. ");
-
- cw = sprbuf; /* current position at top of buffer */
-
-
- for (i = 0; i < BALLS; ++i)
- {
- sprite = sprites [i];
- if (!sprite)
- seppuku ("Zoing! Missing sprite definition. ");
- sprites [i] = cw;
- for (j = 0; j < SIZEOF_SPRITE; ++j)
- *cw++ = *sprite++;
- }
-
- for (i = 0; i < BALLS; ++i)
- {
- sprite = sprites_alt [i];
- if (!sprite)
- seppuku ("Zoing! Missing sprite definition. ");
- sprites_alt [i] = cw;
- for (j = 0; j < SIZEOF_SPRITE; ++j)
- *cw++ = *sprite++;
- }
- }
-
- collisions ()
- {
- /* These are statics so we don't have to worry about stack size. */
- long i, j;
- long dx, dy, dh, halfdh, dvx, dvy, evx, evy;
-
- for (i = cursor ? 0 : 1; i < BALLS; ++i)
- for (j = i+1; j < BALLS; ++j)
- {
- dx = x [i] - x [j];
- dy = y [i] - y [j];
-
- if (dx > D || dx < -D || dy > D || dy < -D)
- continue;
-
- dh = dx*dx + dy*dy;
- /* big chunk of fudge */
- if (dh > D*D + (2 << 2*FRACBITS))
- continue;
-
- dvx = vx [i] - vx [j];
- dvy = vy [i] - vy [j];
-
- if (i == 0)
- {
- dvx = dvx*2 - dvx/2; /* first term: infinite mass */
- dvy = dvy*2 - dvy/2; /* second term: bit inelastic */
- }
-
- evx = dx * dvx + dy * dvy; /* sign of relative speed */
-
- if (evx >= 0) /* same velocity or position, or departing */
- continue;
-
- /* Since energy is proportional to the square of the velocity, simple */
- /* rounding does not work (errors won't necessarily balance over time). */
- /* We'll try to make sure that the middle round value always is rounded */
- /* down by subtracting one from halfdh. */
-
- halfdh = dh/2 - 1; /* if anything we lose energy */
-
- evx = evx * dx;
- if (evx > 0)
- evx = (evx + halfdh) / dh;
- else
- evx = (evx - halfdh) / dh;
- evy = (dx * dvy - dy * dvx) * dx;
- if (evy > 0)
- evy = dvy - (evy + halfdh) / dh;
- else
- evy = dvy - (evy - halfdh) / dh;
-
- if (i) /* cursor doesn't change speed */
- vx [i] -= evx, vy [i] -= evy;
- vx [j] += evx;
- vy [j] += evy;
-
- /* some cute display stuff */
- switch (i) /* personalities */
- {
- case 0:
- if (j > 2)
- angry [j] = 1; /* yuck! */
- break;
- case 1: case 2: /* the fun guys cheer */
- angry [j] = 0; /* everybody up */
- break;
- default:
- angry [i] |= angry [j]; /* infectious grief */
- angry [j] |= angry [i];
- break;
- }
- }
- }
-
- UWORD charlie [] = { 0x0000, 0x0000, 0x0000, 0x07e0, 0x0000, 0x1ff8,
- 0x0020, 0x3ffc, 0x00f0, 0x7ffe, 0x0ff8, 0x7ffe,
- 0x33cc, 0xffff, 0xf3cf, 0xffff, 0xfeff, 0xffff,
- 0xfdbf, 0xffff, 0xfe7f, 0xffff, 0xfe7f, 0xffff,
- 0x7ffe, 0x7ffe, 0x781e, 0x7ffe, 0x3ffc, 0x3ffc,
- 0x1ff8, 0x1ff8, 0x07e0, 0x07e0, 0x0000, 0x0000
- };
-
- UWORD amused [] = { 0x0000, 0x0000, 0x0000, 0x07e0, 0x0000, 0x1ff8,
- 0x0020, 0x3ffc, 0x00f0, 0x7ffe, 0x0ff8, 0x7ffe,
- 0x33cc, 0xffff, 0xf3cf, 0xffff, 0xfeff, 0xffff,
- 0xfdbf, 0xffff, 0xfe7f, 0xffff, 0xfe7f, 0xffff,
- 0x77ee, 0x7ffe, 0x781e, 0x7ffe, 0x3ffc, 0x3ffc,
- 0x1ff8, 0x1ff8, 0x07e0, 0x07e0, 0x0000, 0x0000
- };
-
- UWORD happyw [] = { 0x0000, 0x0000, 0x0000, 0x07e0, 0x0020, 0x1ff8,
- 0x0070, 0x3ffc, 0x0ff8, 0x7ffe, 0x3ffc, 0x7ffe,
- 0xf3cf, 0xffff, 0xf3cf, 0xffff, 0xfeff, 0xffff,
- 0xfdbf, 0xffff, 0xfe7f, 0xffff, 0xeff7, 0xffff,
- 0x77ee, 0x7ffe, 0x781e, 0x7ffe, 0x3ffc, 0x3ffc,
- 0x1ff8, 0x1ff8, 0x07e0, 0x07e0, 0x0000, 0x0000
- };
-
- UWORD angryr [] = { 0x0000, 0x0000, 0x07e0, 0x0000, 0x1ff8, 0x0000,
- 0x3ffc, 0x0000, 0x73ce, 0x0c30, 0x7dbe, 0x0240,
- 0xf3cf, 0x0c30, 0xf3cf, 0x0c30, 0xfeff, 0x0100,
- 0xfdbf, 0x0240, 0xfe7f, 0x0180, 0xffff, 0x0000,
- 0x7ffe, 0x0000, 0x781e, 0x07e0, 0x3ffc, 0x0000,
- 0x1ff8, 0x0000, 0x07e0, 0x0000, 0x0000, 0x0000
- };
-
- UWORD happyr [] = { 0x0000, 0x0000, 0x07e0, 0x0000, 0x1ff8, 0x0000,
- 0x3ffc, 0x0000, 0x7ffe, 0x0000, 0x7ffe, 0x0000,
- 0xf3cf, 0x0c30, 0xf3cf, 0x0c30, 0xffff, 0x0000,
- 0xffff, 0x0000, 0xffff, 0x0000, 0xeff7, 0x1008,
- 0x77ee, 0x0810, 0x781e, 0x07e0, 0x3ffc, 0x0000,
- 0x1ff8, 0x0000, 0x07e0, 0x0000, 0x0000, 0x0000
- };
-
- UWORD sunnyw [] = { 0x0000, 0x0000, 0x07e0, 0x07e0, 0x1ff8, 0x1ff8,
- 0x3ffc, 0x3ffc, 0x7ffe, 0x2184, 0x73ce, 0x4c32,
- 0xf3cf, 0xedb7, 0xffff, 0xe187, 0xfeff, 0xffff,
- 0xfdbf, 0xffff, 0xfe7f, 0xffff, 0xeff7, 0xffff,
- 0x77ee, 0x7ffe, 0x781e, 0x7ffe, 0x3ffc, 0x3ffc,
- 0x1ff8, 0x1ff8, 0x07e0, 0x07e0, 0x0000, 0x0000
- };
-
- UWORD harryr [] = { 0x0000, 0x0000, 0x07e0, 0x07e0, 0x1ff8, 0x1fd8,
- 0x3ffc, 0x3f8c, 0x7ffe, 0x7006, 0x7ffe, 0x4002,
- 0xf3cf, 0x0c30, 0xf3cf, 0x0c30, 0xfeff, 0x0100,
- 0xfdbf, 0x0240, 0xfe7f, 0x0180, 0xeff7, 0x1008,
- 0x77ee, 0x0810, 0x781e, 0x07e0, 0x3ffc, 0x0000,
- 0x1ff8, 0x0000, 0x07e0, 0x0000, 0x0000, 0x0000
- };
-
- /* This program was created with Vladimir Schwartz's editor, PTE, the */
- /* best likely ever to be available for the Amiga. The sprite images */
- /* were designed using Ray R. Larson's SpriteMaker. Funny how Charlie */
- /* Chaplin and his look alike symbolize similar organizations... */
-